package com.treeliked.udpdemo.service.impl;

import com.treeliked.udpdemo.ThreadPoolExecutorFactory;
import com.treeliked.udpdemo.cs.BaseClientServer;
import com.treeliked.udpdemo.cs.UdpServer;
import com.treeliked.udpdemo.model.Constant;
import com.treeliked.udpdemo.model.Message;
import com.treeliked.udpdemo.page.p2.Server;
import com.treeliked.udpdemo.util.MessageUtils;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**
 * udp服务端实现类
 *
 * @author lss
 * @date 2019-01-03, Thu
 */
public class ServerServiceImpl extends AbstractUdpServiceImpl {

    /**
     * socket
     */
    private DatagramSocket ds;

    /**
     * 服务器页面
     */
    private Server server;

    private boolean receiveFlag = false;

    public ServerServiceImpl(DatagramSocket ds, Server server) {
        super(ds);
        this.ds = ds;
        this.server = server;
    }


    @Override
    public void send(Message msg) throws IOException {
        server.addSendMessageAmount();
        server.addSendMessage(msg);
        super.send(msg);
    }

    @Override
    public void startReceive(BaseClientServer cs) throws IOException {
        receiveFlag = true;
        ThreadPoolExecutorFactory.getThreadPoolExecutor().execute(() -> {
            while (receiveFlag) {
                byte[] buf = new byte[Constant.BUFFER_SIZE];
                DatagramPacket packet = new DatagramPacket(buf, buf.length);
                try {
                    ds.receive(packet);
                    UdpServer udpServer = (UdpServer) cs;
                    ThreadPoolExecutorFactory.getThreadPoolExecutor().execute(new MultiThreadClient(server, udpServer, packet));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public void stopReceive() throws IOException {
        receiveFlag = false;
    }
}

class MultiThreadClient implements Runnable {

    /**
     * 测试包错误情况
     */
    public static volatile int foo = 0;

    /**
     * 接受到的packet
     */
    private DatagramPacket packet;


    private Server server;
    /**
     * 服务端server
     */
    private UdpServer udpServer;


    public MultiThreadClient(Server server, UdpServer udpServer, DatagramPacket packet) {
        this.server = server;
        this.udpServer = udpServer;
        this.packet = packet;
    }

    @Override
    public void run() {
        byte[] data = packet.getData();
        Message msg = MessageUtils.bytesToMessage(data);
        try {
            server.addReceiveMessage(msg);
            server.addReceiveMessageAmount();
            if (++foo % 3 == 0) {
                udpServer.sendACKOk(msg.getSrcPost(), msg.getId());
            } else {
                udpServer.sendACKReSend(msg.getSrcPost(), msg.getId());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
